package com.haier.npt.sso.oauth;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.haier.npt.common.JsonResult;
import com.haier.npt.exception.BizBaseException;
import com.haier.npt.security.client.SysAppClient;
import com.haier.npt.security.domain.SysApp;
import com.haier.npt.sso.authentication.cache.TokenCacheService;
import com.haier.npt.sso.domain.HaierUser;
import com.haier.npt.sso.domain.SysUserWapper;
import com.haier.npt.sso.i18n.SSOExceptionCode;
import com.haier.npt.sso.i18n.SSOMessageCode;
import com.haier.npt.sso.service.SysUserService;
import com.haier.npt.sso.utils.AuthorizationHeaderUtil;
import com.haier.npt.sso.utils.AuthorizationUtil;
import com.haier.npt.utils.MessageHelper;


public class OauthServiceImpl implements OauthService, InitializingBean {


	@Autowired
	private TokenCacheService tokenCacheService;

	@Autowired
	private SysUserService sysUserService ;

	@Autowired
	private SysAppClient sysAppClient ;

	@Autowired
	private MessageHelper messageHelper;


	/**
	 * 验证token有效性的url
	 */
	private String checkTokenUrl;

	/**
	 * oauth 登录地址
	 */
	private String loginUrl;


	/**
	 * oauth 获取用户信息地址
	 */
	private String userInfoUri;

	/**
	 * 删除token的url
	 */
	private String deleteTokenUri ;


	public String getDeleteTokenUri() {
		return deleteTokenUri;
	}

	public void setDeleteTokenUri(String deleteTokenUri) {
		this.deleteTokenUri = deleteTokenUri;
	}

	public String getUserInfoUri() {
		return userInfoUri;
	}

	public void setUserInfoUri(String userInfoUri) {
		this.userInfoUri = userInfoUri;
	}

	public String getLoginUrl() {
		return loginUrl;
	}

	public void setLoginUrl(String loginUrl) {
		this.loginUrl = loginUrl;
	}

	public String getCheckTokenUrl() {
		return checkTokenUrl;
	}

	public void setCheckTokenUrl(String checkTokenUrl) {
		this.checkTokenUrl = checkTokenUrl;
	}

	/**
	 * 验证token 的有效性
	 */
	@Override
	public boolean validate(Object token) {
		if (StringUtils.isEmpty(token)) {
			return false;
		}
		return this.tokenCacheService.hasKey((String)token);

	}


	/**
	 * 删除token
	 * @param token
	 * @return
	 */
	public boolean deleteToken(String token){
		String url = getDeleteTokenUri()  +  "?access_token=" + token;
		HttpHeaders header = AuthorizationHeaderUtil.addBasicHeader();
		header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

		RestTemplate restTemplate = new RestTemplate();

		HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(header);
		ResponseEntity<JSONObject> response = null;
		try {
			//删除token
			response = restTemplate.postForEntity(url, httpEntity, JSONObject.class);
			if(response!=null){
				return response.getStatusCode() == HttpStatus.OK ;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return false ;
	}

	/**
	 * 验证客户端凭证是否正确
	 * @param credentials
	 * @return
	 */
	private SysApp  validateCredentials(String credentials){

		SysApp  sysAppInfo =AuthorizationUtil.decodeCredential(credentials);
		if(sysAppInfo ==null){
			throw new BizBaseException(SSOExceptionCode.SYS_APP_ERROR) ; //参数不合法
		}
		//这里验证appkey 的有效性
		JsonResult<SysApp> jsonResult = sysAppClient.valiteAppKey(sysAppInfo);
		if(jsonResult.getCode()!=0){
			throw new BizBaseException(jsonResult);
		}
		return jsonResult.getData() ;

	}

	@Override
	public OauthResult login(String credentials ,String username, String password)  {
		//验证token
		SysApp sysApp = this.validateCredentials(credentials);

		RestTemplate restTemplate = new RestTemplate();

		// 传递用户名密码参数
		LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("username", username);
		params.add("password", password);

		try{
			HttpHeaders header = AuthorizationHeaderUtil.addBasicHeader();
			header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

			HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, header);
			ResponseEntity<OauthResult> response = restTemplate.postForEntity(this.loginUrl, httpEntity, OauthResult.class);
			if (response.getStatusCode() == HttpStatus.OK) {
				//获取oauth body
				OauthResult result = response.getBody() ;

				String token = result.getAccess_token() ;

				/**
				 * 这里保存 token 和appkey的对应关系 ,用于网关快速查寻当前token对应的app
				 */
				 tokenCacheService.saveAppkeyCache(token, sysApp);
				 tokenCacheService.saveTokenOauthInfoCache(token, result);
				 HaierUser loginUser = (HaierUser)this.getUserObject(token) ;
				 tokenCacheService.saveLoginUserCache(token, new SysUserWapper(loginUser, token));
				return result;
			}
		}catch(Exception ex){
			
			 throw new BizBaseException(SSOExceptionCode.USER_LOGIN_FAILED,ex.getCause());
		}

		return null ;
	}


	/**
	 * 根据token 获取用户信息
	 */
	@Override
	public Object getUserObject(String token) {
		Assert.notNull(token, messageHelper.getMessage(SSOMessageCode.TOKEN_NOT_NULL));//"access token must be set");
		RestTemplate restTemplate = new RestTemplate();
		HttpHeaders header = AuthorizationHeaderUtil.addBearerHeader(token);
		//header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(header);
		try {
			ResponseEntity<JSONObject> response = restTemplate.exchange(getUserInfoUri(), HttpMethod.GET, httpEntity,JSONObject.class);
			if (response.getStatusCode() == HttpStatus.OK) {
				JSONObject userObject = response.getBody();
				if (userObject != null) {
					HaierUser sysUser = new HaierUser();
					sysUser.setId(Long.valueOf(userObject.getString("id"))); // 全局id
					sysUser.setMobile(userObject.getString("mobile")); // 手机
					sysUser.setEmail(userObject.getString("email")); // 邮箱
					sysUser.setNickName(userObject.getString("displayName"));//// 用户昵称，用于展示
					sysUser.setExtUserData(userObject.toJSONString());
					sysUser.setUserName(userObject.getString("accountName"));
					sysUser.setAccessToken(token);
					sysUser.setLastLoginDate(new Date());
					sysUser.setSystem(false);
					sysUser.setRegisteDate(new Date());
					sysUser.setCreatedate(new Date());
					return sysUser;
				}
			}
		} catch (Exception ex) {
			throw new BizBaseException(SSOExceptionCode.FETCH_USER_INFO_ERROR,ex);
		}

		return null;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(checkTokenUrl, "checkTokenUrl must be not null ");
		Assert.notNull(loginUrl, "loginUrl must be not null ");
		Assert.notNull(userInfoUri, "userInfoUri must be not null ");
	}
	/**
	 * 通过appKey和token模拟登陆
	 * @param token
	 * @param appKey
	 * @return
	 */
	@Override
	public SysApp login(String token, String appKey) {
		//根据appKey查询sysApp信息
		JsonResult<List<SysApp>> listJsonResult = sysAppClient.listApps();
		if (listJsonResult.getCode() != 0) {
			throw new BizBaseException(listJsonResult);
		}
		List<SysApp> data = listJsonResult.getData();
		SysApp appInfo = null;
		for (SysApp sysApp : data) {
			if (appKey.equals(sysApp.getApp_key())) {
				appInfo = sysApp;
				break;
			}
		}
		tokenCacheService.saveAppkeyCache(token, appInfo);
		if (null != appInfo) {

			//获取用户信息
			HaierUser loginUser = (HaierUser)this.getUserObject(token) ;
			if (null != loginUser) {
				//缓存用户信息和sysApp信息
				tokenCacheService.saveLoginUserCache(token, new SysUserWapper(loginUser, token));
				return appInfo;
			}
		}
		return null;
	}


}
